﻿using System;
using UnityEngine;
using UniFrame.Scene;
using UniFrame.UI;
using UniFrame.Audio;
using System.Collections;

namespace UniFrame
{
    /// <summary>
    /// 框架门面类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class GameFacade<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static T __instance = null;
        /// <summary>
        /// 门面单例
        /// </summary>
        public static T Instance
        {
            get
            {
                if (__instance == null)
                {
                    __instance = FindObjectOfType<T>();
                    if (__instance == null)
                    {
                        GameObject go = new GameObject(typeof(T).ToString());
                        __instance = go.AddComponent<T>();
                    }
                }
                return __instance;
            }
        }
        /// <summary>
        /// 默认场景控制器
        /// </summary>
        public SceneController sceneController { get; protected set; }
        /// <summary>
        /// 默认音频管理器
        /// </summary>
        public AudioManager audioManager { get; protected set; }
        /// <summary>
        /// 当前激活场景默认UI管理器
        /// </summary>
        public UIManager uIManager
        {
            get
            {
                if (sceneController != null && sceneController.CurrentScene != null && sceneController.sceneIsLoaded)
                    return sceneController.CurrentScene.uIManager;
                return null;
            }
        }
        /// <summary>
        /// 初始化框架
        /// </summary>
        protected virtual void Awake()
        {
            if (__instance == null)
                __instance = this as T;
            else
            {
                Destroy(this);
                return;
            }
            DontDestroyOnLoad(this);
            Initialize();
        }
        /// <summary>
        /// 框架逻辑更新
        /// </summary>
        protected virtual void Update()
        {
            sceneController.Update();
        }      
        /// <summary>
        /// 初始化核心框架
        /// </summary>
        protected virtual void Initialize()
        {
            InitAudioSrc();
            InitSceneSrv();                   
        }
        /// <summary>
        /// 初始化场景服务
        /// </summary>
        protected virtual void InitSceneSrv()
        {
            sceneController = new SceneController();
        }
        /// <summary>
        /// 初始化音频服务
        /// </summary>
        protected virtual void InitAudioSrc()
        {
            audioManager = new AudioManager(gameObject);
        }     
        /// <summary>
        /// 加载场景
        /// </summary>
        /// <param name="scene"></param>
        public void LoadScene(BaseScene scene)
        {
            sceneController.SetState(scene);
        }
        /// <summary>
        /// 异步加载场景
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="func"></param>
        public void LoadSceneAsync(BaseScene scene, Action<float> func = null)
        {
            StartCoroutine(sceneController.SetStateAsync(scene, func));
        }
        /// <summary>
        /// 当前激活场景
        /// </summary>
        public BaseScene CurrentScene
        {
            get
            {
                if(sceneController != null && sceneController.sceneIsLoaded)
                    return sceneController.CurrentScene;
                return null;
            }
        }
        /// <summary>
        /// 在当前场景推入一个面板
        /// </summary>
        /// <param name="basePanel"></param>
        public void Push(BasePanel basePanel)
        {
            sceneController.CurrentScene.Push(basePanel);               
        }
        /// <summary>
        /// 在当前场景弹出一个面板
        /// </summary>
        public void Pop()
        {
            sceneController.CurrentScene.Pop();
        }
        /// <summary>
        /// 注册一个音频
        /// </summary>
        /// <param name="uniRes"></param>
        /// <param name="audioType"></param>
        /// <param name="mixerSubPath"></param>
        public void RegisterAudio(UniRes uniRes, Audio.AudioType audioType = Audio.AudioType.UI, string mixerSubPath = null)
        {
            audioManager.Register(uniRes, audioType, mixerSubPath);
        }
        /// <summary>
        /// 播放一个音频
        /// </summary>
        /// <param name="name"></param>
        /// <param name="audioType"></param>
        public void PlayAudio(string name, Audio.AudioType audioType = Audio.AudioType.UI)
        {
            audioManager.Play(name, audioType);
        }
        /// <summary>
        /// 停止播放一个音频
        /// </summary>
        /// <param name="name"></param>
        /// <param name="audioType"></param>
        public void StopAudio(string name, Audio.AudioType audioType)
        {
            audioManager.Stop(name, audioType);
        }
        /// <summary>
        /// 延迟执行
        /// </summary>
        /// <param name="seconds"></param>
        /// <param name="callback"></param>
        /// <param name="enumerator"></param>
        public void DelayExecute(float seconds, Action callback, out IEnumerator enumerator)
        {
            enumerator = Delay(seconds, callback);
            StartCoroutine(enumerator);
        }
        /// <summary>
        /// 条件延迟执行
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="callback"></param>
        /// <param name="enumerator"></param>
        public void DelayExecute(Func<bool> condition, Action callback, out IEnumerator enumerator)
        {
            enumerator = Delay(condition, callback);
            StartCoroutine(enumerator);
        }
        private IEnumerator Delay(float seconds, Action func)
        {
            yield return new WaitForSeconds(seconds);
            func();
        }
        private IEnumerator Delay(Func<bool> condition, Action callback)
        {
            while (!condition())
                yield return null;
            callback();
        }
    }
}
